## Function
### chainAsync
Chains asynchronous functions.
```javascript
const chainAsync = fns => {
  let curr = 0;
  const next = () => fns[curr++](next);
  next();
};
```
example
```javascript
chainAsync([
  next => {
    console.log('0 seconds');
    setTimeout(next, 1000);
  },
  next => {
    console.log('1 second');
  }
]);
```

### converge
Accepts a converging function and a list of branching functions and returns a function that applies each branching function to the arguments and the results of the branching functions are passed as arguments to the converging function.
```javascript
const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
```
example
```javascript
const average = converge((a, b) => a / b, [
  arr => arr.reduce((a, v) => a + v, 0),
  arr => arr.length
]);
average([1, 2, 3, 4, 5, 6, 7]); // 4
```

### curry
Curries a function.
```javascript
const curry = (fn, arity = fn.length, ...args) =>
  arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
```
example
```javascript

curry(Math.pow)(2)(10); // 1024
curry(Math.min, 3)(10)(50)(2); // 2
```

### debounce
Creates a debounced function that delays invoking the provided function until after wait milliseconds have elapsed since the last time the debounced function was invoked.
```javascript
function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}
```
example
```javascript
window.addEventListener(
  'resize',
  debounce(function(evt) {
    console.log(window.innerWidth);
    console.log(window.innerHeight);
  }, 250)
); // Will log the window dimensions at most every 250ms
```

### defer
Defers invoking a function until the current call stack has cleared.
```javascript
const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
```
example
```javascript
// Example A:
defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'

// Example B:
document.querySelector('#someElement').innerHTML = 'Hello';
longRunningFunction(); //Browser will not update the HTML until this has finished
defer(longRunningFunction); // Browser will update the HTML then run the function
```

### delay
Invokes the provided function after wait milliseconds.
```javascript
const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
```
example
```javascript
delay(
  function(text) {
    console.log(text);
  },
  1000,
  'later'
); // Logs 'later' after one second.
```

### once
Ensures a function is called only once.
```javascript
const once = fn => {
  let called = false;
  return function(...args) {
    if (called) return;
    called = true;
    return fn.apply(this, args);
  };
};
```
example
```javascript
const startApp = function(event) {
  console.log(this, event); // document.body, MouseEvent
};
document.body.addEventListener('click', once(startApp)); // only runs `startApp` once upon click
```

### partial
Creates a function that invokes fn with partials prepended to the arguments it receives.
```javascript
const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
```
example
```javascript
const greet = (greeting, name) => greeting + ' ' + name + '!';
const greetHello = partial(greet, 'Hello');
greetHello('John'); // 'Hello John!'
```

### partialRight
Creates a function that invokes fn with partials appended to the arguments it receives.
```javascript
const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
```
example
```javascript
const greet = (greeting, name) => greeting + ' ' + name + '!';
const greetJohn = partialRight(greet, 'John');
greetJohn('Hello'); // 'Hello John!'
```

### runPromisesInSeries
Runs an array of promises in series.
```javascript
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
```
example
```javascript
const delay = d => new Promise(r => setTimeout(r, d));
runPromisesInSeries([() => delay(1000), () => delay(2000)]); // Executes each promise sequentially, taking a total of 3 seconds to complete
```

### throttle
Creates a throttled function that only invokes the provided function at most once per every wait milliseconds
```javascript
const throttle = (fn, wait) => {
  let inThrottle, lastFn, lastTime;
  return function() {
    const context = this,
      args = arguments;
    if (!inThrottle) {
      fn.apply(context, args);
      lastTime = Date.now();
      inThrottle = true;
    } else {
      clearTimeout(lastFn);
      lastFn = setTimeout(function() {
        if (Date.now() - lastTime >= wait) {
          fn.apply(context, args);
          lastTime = Date.now();
        }
      }, wait - (Date.now() - lastTime));
    }
  };
};
```
example
```javascript
window.addEventListener(
  'resize',
  throttle(function(evt) {
    console.log(window.innerWidth);
    console.log(window.innerHeight);
  }, 250)
); // Will log the window dimensions at most every 250ms
```

